#include <func.h>

int epolladd(int epfd,int fd)//在监控队列中添加元素
{
    struct epoll_event event;
    event.data.fd=fd;
    event.events=EPOLLIN;
    int ret=epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&event);
    ERROR_CHECK(ret,-1,"epoll_ctl");
}

int epolldel(int epfd,int fd)//在监控队列中删除元素
{
    struct epoll_event event;
    event.data.fd=fd;
    event.events=EPOLLIN;
    int ret=epoll_ctl(epfd,EPOLL_CTL_DEL,fd,&event);
    ERROR_CHECK(ret,-1,"epoll_ctl");
}

int main(int argc,char* argv[])
{
    ARGS_CHECK(argc,3);
    int sfd;
    sfd=socket(AF_INET,SOCK_STREAM,0);
    ERROR_CHECK(sfd,-1,"socket");
    int reuse=1,ret;//reuse用于在server断开连接时可以重新连接
    ret=setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(int));
    ERROR_CHECK(ret,-1,"setsockopt");
    struct sockaddr_in ser_addr;
    bzero(&ser_addr,sizeof(ser_addr));
    ser_addr.sin_family=AF_INET;
    ser_addr.sin_addr.s_addr=inet_addr(argv[1]);
    ser_addr.sin_port=htons(atoi(argv[2]));
    ret=bind(sfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
    ERROR_CHECK(ret,-1,"bind");
    ret=listen(sfd,10);//监听是否有可读的端口
    ERROR_CHECK(ret,-1,"listen");
    int new_fd;
    struct sockaddr_in cli_addr;
    bzero(&cli_addr,sizeof(cli_addr));
    socklen_t cli_len=sizeof(cli_addr);
    char buf[128]={0};
    int epfd=epoll_create(1);//epfd是监听的队列
    struct epoll_event event,evs[3];
    epolladd(epfd,STDIN_FILENO);
    epolladd(epfd,sfd);
    int ready_fd_num,i;
    while(1)
    {
        ready_fd_num=epoll_wait(epfd,evs,2,-1);
        for(i=0;i<ready_fd_num;i++)
        {
            if(evs[i].data.fd==sfd)//此时是有客户机来请求建立连接
            {
                new_fd=accept(sfd,(struct sockaddr *)&cli_addr,&cli_len);
                ERROR_CHECK(new_fd,-1,"accept");
                printf("client ip is %s,port is %d\n",inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port));
                epolladd(epfd,new_fd);
            }
            if(evs[i].data.fd==STDIN_FILENO)//此时是有键盘输入
            {
                bzero(&buf,sizeof(buf));
                ret=read(STDIN_FILENO,buf,sizeof(buf));
                if(!ret)
                {
                    printf("i want to go\n");
                    return 0;
                }
                send(new_fd,buf,strlen(buf)-1,0);
            }
            if(evs[i].data.fd==new_fd)
            {
                bzero(&buf,sizeof(buf));
                ret=read(new_fd,buf,sizeof(buf));
                if(!ret)
                {
                    printf("byebye\n");
                    epolldel(epfd,new_fd);
                    close(new_fd);
                    break;
                }
                printf("%s\n",buf);
            }
        }
    }
    close(new_fd);
    close(sfd);
    return 0;
}